/* *********************************************************************************  
 *   This file is part of GeometryPlayground.
 *
 *   GeometryPlayground is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   GeometryPlayground is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with GeometryPlayground.  If not, see <http://www.gnu.org/licenses/>.
 **********************************************************************************/
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.*;

import java.applet.*;

public class GeoPlayground extends Applet implements ActionListener,ChangeListener{
	 
  private JPanel	cntrPanel;
  protected static JTabbedPane tabbedPanePlane;
  private JPanel[] canvasPanel;
  protected static GeoCanvas[] canvas;
  public static JRadioButton[] modelButton;
  private JPanel[] infoPanel,modelPanel;
  private JLabel[] infoLabel, modelLabel;
  public static boolean degrees=true;
  public static int whatToDo=-1, model=0, digits=2;
  public static final int	MakePoints=0,   MakeMdPt=1,		MakeInt=2,
  							MakeLines=3,	MakeSegment=4,	MakePerps=5,
  							MakeBisect=6,	MakeCircles=7,  Move=8,
  							FixObject=9,	MeasureDist=10, MeasureAngle=11,
  							MeasureCirc=12, MeasureArea=13,	HideObject=14,
  							LabelObject=15,	MeasureRatio=16,MeasureSum=17,
  							MeasureDiff=18,	MeasureProd=19,
  							ReflectPt=20,	RotatePt=21,	TranslatePt=22,
  							MakeParlls=23,	MeasureTri=24,	MakeRays=25,
  							InvertPt=26,	TrackObject=27;
  static JMenuBar	theMenu;
  JMenu fileMenu,makeMenu,measureMenu,digitMenu,moveMenu,displayMenu,areaMenu,
  		showMenu,modelMenu,angleMenu,scaleMenu;
  JMenuItem newMI,undoMI,
  			pointMI,mdPtMI,intMI,
  			lineMI,segmentMI,perpMI,bisectorMI,parllMI,rayMI,
  			circleMI,
  			distanceMI,angleMI,circumMI,areaMI,triMI,
  			ratioMI,sumMI,diffMI,prodMI,
  			moveMI,fixMI,trackMI,
  			reflectMI,rotateMI,translateMI,invertMI,
  			labelMI,hideMI,
  			showPtsMI,showLnsMI,showCrsMI,showMeasMI,showAllMI,
  			degreeMI,radianMI,
  			scaleUpMI,scaleDnMI;
  static JMenuItem[] modelMI,digitMI;
  public static String[][] modelText={{"","","",""},{"","","",""},{"","","",""},
	  								{"","","",""},{"","","",""},{"","","",""},{"","","",""}};
  public static String[][] tabText={{"","","","","","",""},{"","","","","","",""}};
  public static String copyright;
  
  public static int[] geoModel={0,0,0,3,0,0,2};
  public static int CANVASSIZE=601;
  String textString;
  public void init(){
	getStrings();
    setFont(new Font("Helvetica",Font.PLAIN,12));
    javax.swing.JPopupMenu.setDefaultLightWeightPopupEnabled(false);
    theMenu = new JMenuBar();
    fileMenu = new JMenu(" File ");				theMenu.add(fileMenu);
    newMI = new JMenuItem("New");				fileMenu.add(newMI);
    undoMI = new JMenuItem("Undo");				fileMenu.add(undoMI);
    makeMenu = new JMenu(" Construct ");		theMenu.add(makeMenu);
    pointMI = new JMenuItem("Points");			makeMenu.add(pointMI);
    mdPtMI = new JMenuItem(" Midpoints");		makeMenu.add(mdPtMI);
    intMI = new JMenuItem(" Intersections");	makeMenu.add(intMI);
    makeMenu.addSeparator();
    lineMI = new JMenuItem("Lines");			makeMenu.add(lineMI);
    segmentMI = new JMenuItem(" Segments");		makeMenu.add(segmentMI);
    rayMI = new JMenuItem(" Rays");				makeMenu.add(rayMI);
    perpMI = new JMenuItem(" Perpendiculars");	makeMenu.add(perpMI);
    parllMI = new JMenuItem(" Parallels");		makeMenu.add(parllMI);
    bisectorMI = new JMenuItem(" Bisectors");	makeMenu.add(bisectorMI);
    makeMenu.addSeparator();
    circleMI = new JMenuItem("Circles");		makeMenu.add(circleMI);
    measureMenu = new JMenu(" Measure ");		theMenu.add(measureMenu);
    distanceMI = new JMenuItem("Distance");		measureMenu.add(distanceMI);
    angleMI = new JMenuItem("Angle");			measureMenu.add(angleMI);
    circumMI = new JMenuItem("Circumference");	measureMenu.add(circumMI);
    areaMenu = new JMenu("Area of ");			measureMenu.add(areaMenu);
    areaMI = new JMenuItem("Circles");			areaMenu.add(areaMI);
    triMI = new JMenuItem("Triangles");			areaMenu.add(triMI);
    measureMenu.addSeparator();
    sumMI = new JMenuItem("Sum");				measureMenu.add(sumMI);
    diffMI = new JMenuItem("Difference");		measureMenu.add(diffMI);
    prodMI = new JMenuItem("Product");			measureMenu.add(prodMI);
    ratioMI = new JMenuItem("Ratio");			measureMenu.add(ratioMI);
    measureMenu.addSeparator();
    digitMenu = new JMenu("Digits");			measureMenu.add(digitMenu);
    moveMenu = new JMenu("Manipulate");			theMenu.add(moveMenu);
    moveMI = new JMenuItem("Move");				moveMenu.add(moveMI);
    fixMI = new JMenuItem("Fix an object");		moveMenu.add(fixMI);
    moveMenu.addSeparator();
    trackMI = new JMenuItem("Track point");		moveMenu.add(trackMI);
    moveMenu.addSeparator();
    reflectMI = new JMenuItem("Reflect");		moveMenu.add(reflectMI);
    rotateMI = new JMenuItem("Rotate");			moveMenu.add(rotateMI);
    translateMI = new JMenuItem("Translate");	moveMenu.add(translateMI);
    moveMenu.addSeparator();
    invertMI = new JMenuItem("Invert");			moveMenu.add(invertMI);
    displayMenu = new JMenu(" Display ");		theMenu.add(displayMenu);
    labelMI = new JMenuItem("Label");			displayMenu.add(labelMI);
    displayMenu.addSeparator();
    hideMI = new JMenuItem("Hide");				displayMenu.add(hideMI);
    showMenu = new JMenu("Show all ");			displayMenu.add(showMenu);
    showPtsMI = new JMenuItem("Points");		showMenu.add(showPtsMI);
    showLnsMI = new JMenuItem("Lines");			showMenu.add(showLnsMI);
    showCrsMI = new JMenuItem("Circles");		showMenu.add(showCrsMI);
    showMeasMI = new JMenuItem("Measures");		showMenu.add(showMeasMI);
    showAllMI = new JMenuItem("Objects");		showMenu.add(showAllMI);
    displayMenu.addSeparator();
    modelMenu = new JMenu("Model ");			displayMenu.add(modelMenu);
    displayMenu.addSeparator();
    angleMenu = new JMenu("Angles");			displayMenu.add(angleMenu);
    degreeMI = new JMenuItem("0 \u2264 \u03b8 \u2264 180");			angleMenu.add(degreeMI);
    radianMI = new JMenuItem("0 \u2264 \u03b8 \u2264 \u03c0");		angleMenu.add(radianMI);
    displayMenu.addSeparator();
    scaleMenu = new JMenu("Scale ");			displayMenu.add(scaleMenu);
    scaleUpMI = new JMenuItem("Up");			scaleMenu.add(scaleUpMI);
    scaleDnMI = new JMenuItem("Down");			scaleMenu.add(scaleDnMI); 
    modelMI = new JMenuItem[4];
    for (int i=0;i<4;i++) {
    	modelMI[i] = new JMenuItem("");					modelMenu.add(modelMI[i]);
    	modelMI[i].addActionListener(this);
    	modelMI[i].setEnabled(false);
    	modelMI[i].setVisible(false);
    }
    digitMI = new JMenuItem[7];
    for (int i=0;i<7;i++) {
    	if (digits==i+1) digitMI[i] = new JMenuItem("\u2192");
    	else digitMI[i] = new JMenuItem("");
    	digitMenu.add(digitMI[i]);
    	digitMI[i].setAccelerator(KeyStroke.getKeyStroke((char)('2'+i)));
    	digitMI[i].addActionListener(this);
    }
    newMI.addActionListener(this);
    undoMI.addActionListener(this);
    pointMI.addActionListener(this);
    mdPtMI.addActionListener(this);
    intMI.addActionListener(this);
    lineMI.addActionListener(this);
    segmentMI.addActionListener(this);
    perpMI.addActionListener(this);
    parllMI.addActionListener(this);
    rayMI.addActionListener(this);
    bisectorMI.addActionListener(this);
    circleMI.addActionListener(this);
    distanceMI.addActionListener(this);
    angleMI.addActionListener(this);
    circumMI.addActionListener(this);
    areaMI.addActionListener(this);
    triMI.addActionListener(this);
    ratioMI.addActionListener(this);
    sumMI.addActionListener(this);
    diffMI.addActionListener(this);
    prodMI.addActionListener(this);
    moveMI.addActionListener(this);
    fixMI.addActionListener(this);
    trackMI.addActionListener(this);
    reflectMI.addActionListener(this);
    rotateMI.addActionListener(this);
    translateMI.addActionListener(this);
    invertMI.addActionListener(this);
    hideMI.addActionListener(this);
    showPtsMI.addActionListener(this);
    showLnsMI.addActionListener(this);
    showCrsMI.addActionListener(this);
    showMeasMI.addActionListener(this);
    showAllMI.addActionListener(this);
    labelMI.addActionListener(this);
    degreeMI.addActionListener(this);
    radianMI.addActionListener(this);
    scaleUpMI.addActionListener(this);
    scaleDnMI.addActionListener(this);
    
    setLayout(new BorderLayout());
    cntrPanel = new JPanel();
    tabbedPanePlane = new JTabbedPane();
    canvasPanel = new JPanel[7];
 
    cntrPanel.setLayout(new BorderLayout());
    
    canvas=new GeoCanvas[7];
    infoLabel = new JLabel[7];
    infoPanel = new JPanel[7];
    modelLabel = new JLabel[7];
    modelPanel = new JPanel[7];
    for(int i=0;i<7;i++){
      canvasPanel[i]=new JPanel();
      canvasPanel[i].setLayout(new BorderLayout());
      infoPanel[i]=new JPanel();
      modelPanel[i]=new JPanel();
      switch(i){
      case 0:
          canvas[i] = new GeoCanvas(new SphericalGeometry());
          textString= "Spherical";
          break;
      case 1:
    	  canvas[i] = new GeoCanvas(new ProjectiveGeometry());
    	  textString= "Projective";
    	  break;      
      case 2:
          canvas[i] = new GeoCanvas(new EuclideanGeometry());
          textString= "Euclidean";
          break;
      case 3:
    	  canvas[i] = new GeoCanvas(new HyperbolicGeometry());
    	  textString= "Hyperbolic";
    	  break;
      case 4:
    	  canvas[i] = new GeoCanvas(new ManhattanGeometry());
		  textString= "Manhattan";
		  break;
	  case 5: 
		  canvas[i] = new GeoCanvas(new ToroidalGeometry());
    	  textString= "Toroidal";
    	  break;
      case 6:
    	  canvas[i] = new GeoCanvas(new ConicalGeometry());
    	  textString= "Conical";
    	  break;
      }
      tabbedPanePlane.addTab(textString, canvasPanel[i]);
      canvas[i].setBackground(Color.white);
      canvas[i].setSize(CANVASSIZE,CANVASSIZE);
      canvasPanel[i].add("Center",canvas[i]);
      textString="<html><font color='blue'>&nbsp;&nbsp;Geometry Sandbox \u00a9 2010 by D. Heath, PLU, and J. Jacobs, UW&nbsp;&nbsp;</font></html>";
      infoLabel[i]=new JLabel(textString);
      infoPanel[i].add(infoLabel[i]);
      textString="<html><font color='blue'>"+modelText[i][geoModel[i]]+"</font></html>";
      modelLabel[i]=new JLabel(textString);
      modelPanel[i].add(modelLabel[i]);
      canvasPanel[i].add("South",infoPanel[i]);
      canvasPanel[i].add("North",modelPanel[i]);
      canvas[i].addChangeListener(this);
    }
    tabbedPanePlane.addChangeListener(this);
    tabbedPanePlane.setSelectedIndex(2);
	cntrPanel.add("Center",tabbedPanePlane);
    add("Center",cntrPanel);
    add(theMenu,"North");
    setInfoTA();
  }
  private void getStrings() {
	  copyright="Geometry Sandbox \u00A9 2010 by D. Heath, PLU, and J. Jacobs, UW";
      tabText[0][0]="Spherical";
      tabText[0][1]="Projective";
      tabText[0][2]="Euclidean";
      tabText[0][3]="Hyperbolic";
      tabText[0][4]="Manhattan";
      tabText[0][5]="Toroidal";
      tabText[0][6]="Conical";
	  modelText[0][0]="Sphere Model";
      modelText[0][1]="Plane Model";
      modelText[0][2]="Mercator Model";
      modelText[1][0]="Half-Sphere Model";
      modelText[1][1]="Plane Model";
      modelText[2][0]="Plane Model";
      modelText[2][1]="Projective Model";
      modelText[2][2]="Inverted Model";
      modelText[3][0]="Poincar\u00e9 Model";
      modelText[3][1]="Beltrami-Klein Model";
      modelText[3][2]="Half-Plane Model";
      modelText[3][3]="Minkowski-Weierstrass Model";
      modelText[4][0]="Plane Model";
      modelText[5][0]="Square Model";
      modelText[5][1]="Plane Tiling Model";
      modelText[5][2]="Donut Model";
      modelText[6][0]="Plane Model";
      modelText[6][1]="Plane Tiling Model";
      modelText[6][2]="Cone Model";
  }
  private void setInfoTA() {
    switch(whatToDo) {
    case MakePoints:	textString="<html><font color='red'>Make points</font><font color='blue'> by clicking in the geometry, or on an object.</font></html>";	break;
    case MakeMdPt:		textString="<html><font color='blue'>Select two points to <font color='red'>construct the midpoint</font> of their segment.</font></html>";	break;
    case MakeInt:		textString="<html><font color='blue'>Select two constructions to find their <font color='red'>intersection</font>.</font></html>";		break;
    case MakeSegment:	textString="<html><font color='blue'>Select two points to <font color='red'>construct the segment</font> they determine.</font></html>";	break;
    case MakeLines:		textString="<html><font color='blue'>Select two points to <font color='red'>construct the line</font> they determine.</font></html>";	break;
    case MakePerps:		textString="<html><font color='blue'>Select a line and a point to <font color='red'>construct the perpendicular</font>.</font></html>";	break;
    case MakeParlls:	textString="<html><font color='blue'>Select a line and a point to <font color='red'>construct the parallel</font> line(s).</font></html>";	break;
    case MakeRays:		textString="<html><font color='blue'>Select two points to <font color='red'>construct the ray</font> they determine.</font></html>";	break;
    case MakeBisect:	textString="<html><font color='blue'>Select points A, B, C to <font color='red'>construct the bisector</font> of \u2220ABC.</font></html>";	break;
    case MakeCircles:	textString="<html><font color='red'>Construct a circle</font> <font color='blue'>by selecting a center and a point on it.</font></html>";	break;
    case MeasureDist:	textString="<html><font color='blue'>Select two points to <font color='red'>measure the distance</font> between them.</font></html>";	break;
    case MeasureAngle:	textString="<html><font color='blue'>Select points A, B, C to <font color='red'>measure \u2220ABC</font>.</font></html>";break;
  	case MeasureCirc:	textString="<html><font color='blue'>Select a circle to <font color='red'>measure its circumference</font>.</font></html>";	break;
    case MeasureArea:	textString="<html><font color='blue'>Select a circle to <font color='red'>measure its area</font>.</font></html>";	break;
    case MeasureTri:	textString="<html><font color='blue'>Select three points to <font color='red'>measure the area of the triangle</font> they determine.</font></html>";	break;
    case MeasureRatio:	textString="<html><font color='blue'>Select measures X and Y to <font color='red'>measure the ratio</font> X/Y.</font></html>";break;
    case MeasureSum:	textString="<html><font color='blue'>Select measures X and Y to <font color='red'>measure the sum</font> X+Y.</font></html>";	break;
    case MeasureDiff:	textString="<html><font color='blue'>Select measures X and Y to <font color='red'>measure the difference</font> X-Y.</font></html>";	break;
    case MeasureProd:	textString="<html><font color='blue'>Select measures X and Y to <font color='red'>measure the product</font> X\u00b7Y.</font></html>";	break;
    case Move:			textString="<html><font color='blue'>Click and drag a point to <font color='red'>move</font> it, or drag the space itself.</font></html>";		break;
    case FixObject:		textString="<html><font color='blue'>Select an object to <font color='red'>fix</font> it in space.</font></html>";	break;
    case TrackObject:	textString="<html><font color='blue'>Select a point to <font color='red'>track</font>.</font></html>";		break;
    case ReflectPt:		textString="<html><font color='blue'>Select a line of reflection and a point to <font color='red'>reflect</font>.</font></html>";	break;
    case RotatePt:		textString="<html><font color='blue'>Select angle measure X and point Y to <font color='red'>rotate</font> point Y by \u2220X.</font></html>";	break;
    case TranslatePt:	textString="<html><font color='blue'>Select distance measure X and a point Y to <font color='red'>translate</font> point Y by vector X.</font></html>";	break;
    case InvertPt:		textString="<html><font color='blue'>Select a circle of inversion and a point to <font color='red'>invert</font>.</font></html>";	break;
    case HideObject:	textString="<html><font color='blue'>Select an object to <font color='red'>hide</font> it.</font></html>";	break;
    case LabelObject:	textString="<html><font color='blue'>Select an object to show or hide its <font color='red'>label</font>. Right click to edit it.</font></html>";	break;
	default:			textString="<html><font color='blue'>&nbsp;&nbsp;Geometry Sandbox \u00a9 2010 by D. Heath, PLU, and J. Jacobs, UW&nbsp;&nbsp;</font></html>";		break;
    }
    infoLabel[tabbedPanePlane.getSelectedIndex()].setText(textString);
    if (tabbedPanePlane.getSelectedIndex()>4) {
		intMI.setEnabled(false);
		reflectMI.setEnabled(false);
		rotateMI.setEnabled(false);
		invertMI.setEnabled(false);
		if (tabbedPanePlane.getSelectedIndex()==6){
			translateMI.setEnabled(false);
			fixMI.setEnabled(false);
			parllMI.setEnabled(false);
		}
		else {
			translateMI.setEnabled(true);
			fixMI.setEnabled(true);
			parllMI.setEnabled(true);
		}
	}
	else {
		intMI.setEnabled(true);
		reflectMI.setEnabled(true);
		rotateMI.setEnabled(true);
		invertMI.setEnabled(true);
	}
	setupModel();
	canvas[tabbedPanePlane.getSelectedIndex()].repaint();
	infoPanel[tabbedPanePlane.getSelectedIndex()].repaint();
  }
  public void setupModel() {
	  geoModel[tabbedPanePlane.getSelectedIndex()]=model;
	  modelLabel[tabbedPanePlane.getSelectedIndex()].setText("<html><font color='blue'>"+
			modelText[tabbedPanePlane.getSelectedIndex()][model]+"</font></html>");
	  if ((whatToDo==MakeInt || whatToDo==ReflectPt || whatToDo==RotatePt || whatToDo==InvertPt)
			  && tabbedPanePlane.getSelectedIndex()>4) whatToDo=MakePoints;
	  if ((whatToDo==MakeParlls) && tabbedPanePlane.getSelectedIndex()<2) whatToDo=MakePoints;
	  if (tabbedPanePlane.getSelectedIndex()<2 || tabbedPanePlane.getSelectedIndex()==6)	parllMI.setEnabled(false);
	  else parllMI.setEnabled(true);
	  if ((tabbedPanePlane.getSelectedIndex()==2 && model==0) ||
		  (tabbedPanePlane.getSelectedIndex()==3 && model==3) ||
		  (tabbedPanePlane.getSelectedIndex()==1 && model==1) ||
		  (tabbedPanePlane.getSelectedIndex()==0 && model==1) ||
		  (tabbedPanePlane.getSelectedIndex()==6)) {
		    scaleMenu.setEnabled(true);
		    scaleUpMI.setEnabled(true);
		    scaleDnMI.setEnabled(true);
	  }
	  else {
	        scaleMenu.setEnabled(false);
		    scaleUpMI.setEnabled(false);
		    scaleDnMI.setEnabled(false);
	  }
  }
  public void stateChanged(ChangeEvent e) {
    model=geoModel[tabbedPanePlane.getSelectedIndex()];
    setInfoTA();
  }
  public void actionPerformed(ActionEvent e){
	  canvas[tabbedPanePlane.getSelectedIndex()].clickedList.clear();
	  if (e.getSource()==pointMI)	whatToDo=MakePoints;
	  if (e.getSource()==mdPtMI)	whatToDo=MakeMdPt;
	  if (e.getSource()==intMI)		whatToDo=MakeInt;
	  if (e.getSource()==lineMI)	whatToDo=MakeLines;
	  if (e.getSource()==segmentMI)	whatToDo=MakeSegment;
	  if (e.getSource()==perpMI)	whatToDo=MakePerps;
	  if (e.getSource()==parllMI)	whatToDo=MakeParlls;
	  if (e.getSource()==rayMI)		whatToDo=MakeRays;
	  if (e.getSource()==bisectorMI)whatToDo=MakeBisect;
	  if (e.getSource()==circleMI)	whatToDo=MakeCircles;
	  if (e.getSource()==distanceMI)whatToDo=MeasureDist;
	  if (e.getSource()==degreeMI)	degrees=true;
	  if (e.getSource()==radianMI)	degrees=false;
	  if (e.getSource()==angleMI)	whatToDo=MeasureAngle;
	  if (e.getSource()==circumMI)	whatToDo=MeasureCirc;
	  if (e.getSource()==areaMI)	whatToDo=MeasureArea;
	  if (e.getSource()==triMI)		whatToDo=MeasureTri;
	  if (e.getSource()==ratioMI)	whatToDo=MeasureRatio;
	  if (e.getSource()==sumMI)		whatToDo=MeasureSum;
	  if (e.getSource()==diffMI)	whatToDo=MeasureDiff;
	  if (e.getSource()==prodMI)	whatToDo=MeasureProd;
	  if (e.getSource()==moveMI)	whatToDo=Move;
	  if (e.getSource()==fixMI)		whatToDo=FixObject;
	  if (e.getSource()==trackMI)	whatToDo=TrackObject;
	  if (e.getSource()==reflectMI)	whatToDo=ReflectPt;
	  if (e.getSource()==rotateMI)	whatToDo=RotatePt;
	  if (e.getSource()==translateMI)whatToDo=TranslatePt;
	  if (e.getSource()==invertMI)	whatToDo=InvertPt;
	  if (e.getSource()==hideMI)	whatToDo=HideObject;
	  if (e.getSource()==labelMI)	whatToDo=LabelObject;
	  if (e.getSource()==scaleUpMI)	{
		  canvas[tabbedPanePlane.getSelectedIndex()].geometry.setScale(1);
		  double[] v={0,0,0};
		  if (tabbedPanePlane.getSelectedIndex()==6)
			  for (int i=0;i<canvas[tabbedPanePlane.getSelectedIndex()].list.size();i++) {
				  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).update();
				  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).getNewXYZ(v);
				  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).setXYZ(v);
			  }
		  
	  }
	  if (e.getSource()==scaleDnMI) {
		  canvas[tabbedPanePlane.getSelectedIndex()].geometry.setScale(-1);
		  double[] v={0,0,0};
		  if (tabbedPanePlane.getSelectedIndex()==6)
			  for (int i=0;i<canvas[tabbedPanePlane.getSelectedIndex()].list.size();i++) {
				  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).update();
				  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).getNewXYZ(v);
				  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).setXYZ(v);
			  }
	  }for (int i=0;i<4;i++) if (e.getSource()==modelMI[i]) {
		getStrings();
		model=i;
		setupModel();
	  }
	  if (e.getSource()==newMI)	{
		  canvas[tabbedPanePlane.getSelectedIndex()].trackPoint=null;
		  canvas[tabbedPanePlane.getSelectedIndex()].fixedObject=null;
		  canvas[tabbedPanePlane.getSelectedIndex()].list.clear();
		  canvas[tabbedPanePlane.getSelectedIndex()].potentialClick=null;
		  canvas[tabbedPanePlane.getSelectedIndex()].clickedList.clear();
		  whatToDo=-1;
	  }
	  if (e.getSource()==showPtsMI)	{
		  for (int i=0;i<canvas[tabbedPanePlane.getSelectedIndex()].list.size();i++)
	          if (canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).getType()>0 &&
	        	  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).getType()<30)
			  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).setShown(true);
	  }
	  if (e.getSource()==showLnsMI)	{
		  for (int i=0;i<canvas[tabbedPanePlane.getSelectedIndex()].list.size();i++)
	          if (canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).getType()<0)
			  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).setShown(true);
	  }
	  if (e.getSource()==showMeasMI)	{
		  for (int i=0;i<canvas[tabbedPanePlane.getSelectedIndex()].list.size();i++)
	          if (canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).getType()>30)
			  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).setShown(true);
	  }
	  if (e.getSource()==showCrsMI)	{
		  for (int i=0;i<canvas[tabbedPanePlane.getSelectedIndex()].list.size();i++)
	          if (canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).getType()==0)
			  canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).setShown(true);
	  }
	  if (e.getSource()==showAllMI) {
		  for (int i=0;i<canvas[tabbedPanePlane.getSelectedIndex()].list.size();i++)
	          canvas[tabbedPanePlane.getSelectedIndex()].list.get(i).setShown(true);
	  }
	    
	  if (e.getSource()==undoMI){
	    	if (canvas[tabbedPanePlane.getSelectedIndex()].list.size()>0) {
	    		int n = canvas[tabbedPanePlane.getSelectedIndex()].list.getLast().getType();
	    		if (n==11) // if type=CircIntCirc11 then we undo 4 points at once
	    			for (int i=0;i<4;i++) {
	    				if (canvas[tabbedPanePlane.getSelectedIndex()].trackPoint==canvas[tabbedPanePlane.getSelectedIndex()].list.getLast())
	    	    			canvas[tabbedPanePlane.getSelectedIndex()].trackPoint=null; 	// if undoing a trackPoint, nullify the trackPoint.
	    	    		if (canvas[tabbedPanePlane.getSelectedIndex()].fixedObject==canvas[tabbedPanePlane.getSelectedIndex()].list.getLast())
	    	    			canvas[tabbedPanePlane.getSelectedIndex()].fixedObject=null; // if undoing a fixed object, nullify the fixedObject.
	    	    		canvas[tabbedPanePlane.getSelectedIndex()].list.removeLast();
	    			}
	    		else if (n==9 || n==7 || n==5 || n==-5) // if type=CircIntCirc01, CircIntLine1, LineIntLine1, or Parll1
	    			for (int i=0;i<2;i++) {				// we undo 2 objects at once.
	    				if (canvas[tabbedPanePlane.getSelectedIndex()].trackPoint==canvas[tabbedPanePlane.getSelectedIndex()].list.getLast())
	    	    			canvas[tabbedPanePlane.getSelectedIndex()].trackPoint=null; 	// if undoing a trackPoint, nullify the trackPoint.
	    	    		if (canvas[tabbedPanePlane.getSelectedIndex()].fixedObject==canvas[tabbedPanePlane.getSelectedIndex()].list.getLast())
	    	    			canvas[tabbedPanePlane.getSelectedIndex()].fixedObject=null; // if undoing a fixed object, nullify the fixedObject.
	    	    		canvas[tabbedPanePlane.getSelectedIndex()].list.removeLast();
	    			}
	    		else {
    			if (canvas[tabbedPanePlane.getSelectedIndex()].trackPoint==canvas[tabbedPanePlane.getSelectedIndex()].list.getLast())
	    			canvas[tabbedPanePlane.getSelectedIndex()].trackPoint=null; 	// if undoing a trackPoint, nullify the trackPoint.
	    		if (canvas[tabbedPanePlane.getSelectedIndex()].fixedObject==canvas[tabbedPanePlane.getSelectedIndex()].list.getLast())
	    			canvas[tabbedPanePlane.getSelectedIndex()].fixedObject=null;
    			canvas[tabbedPanePlane.getSelectedIndex()].list.removeLast();	// otherwise we undo one at a time
    		}
    		canvas[tabbedPanePlane.getSelectedIndex()].clickedList.clear();
	    	canvas[tabbedPanePlane.getSelectedIndex()].potentialClick=null;
	    	}
	    	//if (canvas[tabbedPanePlane.getSelectedIndex()].list.size()==0) undoMI.setEnabled(false);
	    }
     
    for (int i=0;i<7;i++) if (e.getSource()==digitMI[i]) {
    	digitMI[digits-1].setText("");
    	digits=i+1;
    	digitMI[digits-1].setText("\u2192");
    }
	  
    setInfoTA();
  }
  public static int getHght() {
    return (int)MathEqns.max(canvas[tabbedPanePlane.getSelectedIndex()].getHeight(),4);
  }
  public static int getWdth() {
    return (int)MathEqns.max(canvas[tabbedPanePlane.getSelectedIndex()].getWidth(),4);
  }
}